
import java.math.BigInteger;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.spec.*;

/**
 * DiffieHellman.java
 * 
 * This class has all DiffieHellman functions.  It uses many of the built in java libraries
 * to do this.
 * 
 */
public class DiffieHellman
{
	//essential privatekey var
	PrivateKey privateKey;
	
	//generates P and G by finding prime numbers
	BigInteger[] GeneratePG()
	{
		BigInteger[] ret = new BigInteger[2];
		int bitLength = 512; // 512 bits
	    SecureRandom rnd = new SecureRandom();
	    ret[0] = BigInteger.probablePrime(bitLength, rnd);
	    ret[1] = BigInteger.probablePrime(bitLength, rnd);
		return ret;
	}
	
	//creates an integer to send. uses the values from the GeneratePG method
	byte[] CreateSendInteger(BigInteger p, BigInteger g, int keybits)
	{
		try {
			//Generates the diffiehellman keys using the KeyGenerator class 
		    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH");
		    DHParameterSpec dhSpec = new DHParameterSpec(p, g, keybits);
		    keyGen.initialize(dhSpec);
		    KeyPair keypair = keyGen.generateKeyPair();

		    // Stores the generated keys
		    privateKey = keypair.getPrivate();
		    PublicKey publicKey = keypair.getPublic();

		    // Gives back the public key
		    return publicKey.getEncoded();
		} catch (java.security.InvalidAlgorithmParameterException e) {
		} catch (java.security.NoSuchAlgorithmException e) {
		}
		return null;
	}
	
	//Creates the full key from the other party's publicKeyBytes
	SecretKey CreateFullKey(byte[] publicKeyBytes)
	{
		try {
		    // makes the key bytes into a public key object
		    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
		    KeyFactory keyFact = KeyFactory.getInstance("DH");
		    PublicKey publicKey = keyFact.generatePublic(x509KeySpec);

		    // Prepare to generate the secret key object from our privatekey and publicKey
		    KeyAgreement ka = KeyAgreement.getInstance("DH");
		    ka.init(privateKey);
		    ka.doPhase(publicKey, true);

		    // Our algorithm we are using for encryption
		    String algorithm = "DES";

		    // Generate the secret key and return to user
		    return ka.generateSecret(algorithm);
		    
		}
		
		//catching some common errors(none of them occur tho)
		catch (java.security.InvalidKeyException e) {
			
		} 
		catch (java.security.spec.InvalidKeySpecException e) {
			
		} 
		catch (java.security.NoSuchAlgorithmException e) {
			
		}
		//default return value
		return null;
		
	}
	
}